package me.flyray.bsin.server.service;

import lombok.extern.slf4j.Slf4j;
import me.flyray.bsin.blockchain.core.BlockchainService;
import me.flyray.bsin.blockchain.transaction.MultiChainTransactionService;
import me.flyray.bsin.blockchain.config.BlockchainProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.concurrent.CompletableFuture;

/**
 * 优化后的资金归集服务
 * 使用现有的区块链引擎和事件驱动架构
 */
@Slf4j
@Service
public class OptimizedCashConcentrationService {
    
    @Autowired
    private MultiChainTransactionService transactionService;
    
    @Autowired
    private BlockchainProperties blockchainProperties;
    
    @Autowired
    private BlockchainService blockchainService;
    
    /**
     * 资金归集请求
     */
    public static class CashConcentrationRequest {
        private String chainName;
        private String fromAddress;
        private String toAddress;
        private String contractAddress;
        private BigInteger amount;
        private BigInteger decimals;
        
        // Getters and Setters
        public String getChainName() { return chainName; }
        public void setChainName(String chainName) { this.chainName = chainName; }
        
        public String getFromAddress() { return fromAddress; }
        public void setFromAddress(String fromAddress) { this.fromAddress = fromAddress; }
        
        public String getToAddress() { return toAddress; }
        public void setToAddress(String toAddress) { this.toAddress = toAddress; }
        
        public String getContractAddress() { return contractAddress; }
        public void setContractAddress(String contractAddress) { this.contractAddress = contractAddress; }
        
        public BigInteger getAmount() { return amount; }
        public void setAmount(BigInteger amount) { this.amount = amount; }
        
        public BigInteger getDecimals() { return decimals; }
        public void setDecimals(BigInteger decimals) { this.decimals = decimals; }
    }
    
    /**
     * 处理资金归集
     */
    public CompletableFuture<String> processCashConcentration(CashConcentrationRequest request) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                // 1. 检查账户余额
                String balanceStr = transactionService.getBalance(request.getChainName(), request.getFromAddress());
                BigInteger balance = new BigInteger(balanceStr);
                
                if (balance.compareTo(request.getAmount()) < 0) {
                    throw me.flyray.bsin.blockchain.exception.BlockchainException.insufficientBalance("账户余额不足");
                }
                
                // 2. 智能 Gas 费管理
                if (needsGasRefuel(request.getChainName(), request.getToAddress())) {
                    refuelAccount(request.getChainName(), request.getToAddress());
                }
                
                // 3. 执行转账
                String txHash = transactionService.tokenTransfer(
                    request.getChainName(),
                    request.getFromAddress(),
                    request.getToAddress(),
                    request.getContractAddress(),
                    request.getAmount(),
                    request.getDecimals()
                );
                
                // 4. 记录成功指标
                blockchainService.recordTransactionSuccess(request.getChainName(), request.getContractAddress());
                
                // 5. 发布成功事件
                blockchainService.publishTransactionConfirmed(
                    request.getChainName(),
                    txHash,
                    request.getFromAddress(),
                    request.getToAddress(),
                    request.getAmount(),
                    System.currentTimeMillis(),
                    request.getContractAddress()
                );
                
                log.info("资金归集成功: chain={}, txHash={}", request.getChainName(), txHash);
                return txHash;
                
            } catch (Exception e) {
                // 记录失败指标
                blockchainService.recordTransactionFailure(request.getChainName(), e.getClass().getSimpleName());
                
                // 发布失败事件
                blockchainService.publishTransactionFailed(
                    request.getChainName(),
                    null,
                    request.getFromAddress(),
                    request.getToAddress(),
                    request.getAmount(),
                    e.getMessage(),
                    request.getContractAddress()
                );
                
                log.error("资金归集失败: chain={}", request.getChainName(), e);
                throw new RuntimeException(e);
            }
        });
    }
    
    /**
     * 检查是否需要加油
     */
    private boolean needsGasRefuel(String chainName, String address) {
        try {
            BlockchainProperties.ChainConfig chainConfig = blockchainProperties.getChainConfig(chainName);
            String balanceStr = transactionService.getBalance(chainName, address);
            BigInteger balance = new BigInteger(balanceStr);
            BigInteger requiredGas = new BigInteger(chainConfig.getNativeGasLimit());
            
            return balance.compareTo(requiredGas) < 0;
        } catch (Exception e) {
            log.error("检查 Gas 余额失败: chain={}, address={}", chainName, address, e);
            return false;
        }
    }
    
    /**
     * 给账户加油
     */
    private void refuelAccount(String chainName, String toAddress) {
        try {
            BlockchainProperties.ChainConfig chainConfig = blockchainProperties.getChainConfig(chainName);
            // 使用默认的 Gas 地址和金额，这里需要根据实际业务逻辑调整
            String gasAddress = "0x..."; // 需要配置实际的 Gas 地址
            BigInteger gasAmount = new BigInteger(chainConfig.getNativeGasLimit());
            
            // 发送原生代币作为 Gas 费
            String txHash = transactionService.nativeTokenTransfer(chainName, gasAddress, toAddress, gasAmount);
            log.info("账户加油成功: chain={}, address={}, txHash={}", chainName, toAddress, txHash);
            
        } catch (Exception e) {
            log.error("账户加油失败: chain={}, address={}", chainName, toAddress, e);
            // 发布 Gas 不足事件
            blockchainService.publishInsufficientGas(chainName, toAddress, "required", "current");
        }
    }
    
    /**
     * 批量资金归集
     */
    public CompletableFuture<Void> batchCashConcentration(java.util.List<CashConcentrationRequest> requests) {
        java.util.List<CompletableFuture<String>> futures = requests.stream()
            .map(this::processCashConcentration)
            .collect(java.util.stream.Collectors.toList());
        
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
    }
}